iT邦幫忙

2022 iThome 鐵人賽

DAY 26
0
自我挑戰組

被MongoDB用Aggregate暴打的後端小菜雞日記系列 第 26

被MongoDB用Index暴打的後端小菜雞日記-day26-Index Property

  • 分享至 

  • xImage
  •  

前幾天大致介紹過如何建立好一個index,以及主要參照的規則,今天則是要介紹各種不同 index 的特性,以及它們各自會用到的場景。

Unique Indexes

在我們第二天在介紹索引時有提到,MongoDB會自動幫_id建立unique index,除了可以加快使用_id搜尋資料的速度以外,還可以確保_id值不會重複。

事實上unique index也可以用在其他欄位上,只要在建立index時候,多加入unique: true的設定,詳細語法如下。

// 語法架構
db.collection.createIndex( <key and index type specification>, { unique: true } )

// Single Field Indexes 寫法
product.createIndex( { name: 1 }, { unique: true } )

// Compound Index 寫法
user.createIndex( { name: 1, email: 1 }, { unique: true } )

使用上必須注意,如果建立時索引欄位有重複的值,Unique Indexes無法被建立,以及在寫入資料的時候,如果寫入索引欄位有相同值,也會出錯。

ps.只允許索引欄位有一個值是缺漏的,缺漏的值會用null替代,下一個缺漏再用null替代,就會違反沒有重複的值出現的條件。

因此unique index蠻適合用在,想要避免重複資料寫入的場景,例如:在註冊時想要避免,使用者重複使用相同的信箱註冊,這時候就可以再email這個欄位加上unique index。在使用信箱登入的時候,也可以通過index加快尋找使用者資料的速度。


Partial Indexes

可以只針對部分資料建立索引,例如:所有商品類別中,只有3C類別的產品賣得最好,最常被消費者搜尋,因此我們只針對3C類別的產品建立price欄位的索引。

這時候可以用以下指令,partialFilterExpression後面寫入資料塞選的條件。

product.createIndex(
  { price: 1 },
  { partialFilterExpression: { category: { $eq: "3C" } } }
)

在使用條件篩選資料時,只能使用以下的操作符

  1. 相等條件,可以直接寫field: value 或是使用$eq
  2. 大小判斷,可以使用$gt、$gte、$lt、$lte
  3. 邏輯判斷,可以使用$and、$or
  4. 其他類型:$type、$in、$exists: true

TTL Indexes

TTl index 這個索引類型,是我覺得在MongoDB蠻特別、也蠻好用的一個功能,它可以讓資料根據特定欄位設定的時間,自動刪除不會用到的資料。

例如:使用者的聊天訊息,我們只想保留6個月,避免資料庫一直寫入太多資料都未清理,節省資料庫的空間,這時候可以使用以下指令。

// 透過 expireAfterSeconds設定資料過期的時間,單位是秒
message.createIndex( { create_time: 1 }, { expireAfterSeconds: 15552000 } )

使用上必須注意

  1. 它屬於single-field indexes的一種,只能用一個欄位來當索引值
  2. 如果索引欄位的資料,並不是日期,則該資料不會過期
  3. 如果資料沒有包含到indexed field,則該資料不會過期

Hidden Indexes

可以暫時隱藏索引,而非實際刪除索引,讓開發人員來評估,使用索引使用索引前後效能差異。

以商品資料做舉例,我們現在有針對price這個欄位做索引。

// 建立索引時,可以透過hidden來設定,是否隱藏索引
product.createIndex(
   { price: 1 },
   { hidden: true }
);

// 可以透過getIndexes來查看,collection目前包含哪些索引,索引是否被隱藏
prodct.getIndexes()

// 回傳結果
[
   {
      "v" : 2,
      "key" : {
         "_id" : 1
      },
      "name" : "_id_"
   },
   {
      "v" : 2,
      "key" : {
         "price" : 1
      },
      "name" : "price_1",
      "hidden" : true  // 在這個欄位可以看到索引是否被隱藏
   }
]

 // 如果想要將隱藏的索引,改成使用索引,可以使用unhideIndex,並帶入索引名稱
 product.unhideIndex( "price_1" );  
 
 // 如果想要將原本有在使用的索引隱藏,可以使用 hideIndex
 product.hideIndex( "price_1" );  

使用上必須注意

  1. 如果隱藏的是Unique Indexes,仍舊會限制索引欄位不能有重複的值
  2. 即使隱藏索引,在寫入資料時,仍舊會消耗硬碟資源和記憶體
  3. 無法隱藏 _id index

本篇文章同步放在我的部落格,大家有空可以進來逛逛


上一篇
被MongoDB用Index暴打的後端小菜雞日記-day25-建立index的順序 (ESR rule)
下一篇
被MongoDB用Index暴打的後端小菜雞日記-day27- Index Types
系列文
被MongoDB用Aggregate暴打的後端小菜雞日記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言